﻿using System.IO;
using System;

const express = require('express');
const WebSocket = require('ws');
const mqtt = require('mqtt');
const path = require('path');

// 配置Express静态文件服务
const app = express();
app.use(express.static (path.join(__dirname, 'public')));

// 启动HTTP服务器
const httpServer = app.listen(3000, () => {
    console.log('HTTP服务器运行在端口 3000');
});

// 启动WebSocket服务器，独立于HTTP服务
const wss = new WebSocket.Server({ port: 8080 });
wss.on('listening', () => {
    console.log('WebSocket服务器运行在端口 8080');
});

// MQTT配置与连接
const mqttClient = mqtt.connect('mqtt://47.109.144.136:1883', {
  username: 'tjy',
  password: 'tjy20040512',
  clientId: 'web-server-' + Math.random().toString(16).substr(2, 8)
});

// MQTT连接状态处理
mqttClient.on('connect', () => {
    console.log('MQTT连接成功');
    mqttClient.subscribe('gps/data');
});

mqttClient.on('error', (err) => {
    console.error('MQTT连接错误:', err);
});

mqttClient.on('close', () => {
    console.log('MQTT连接已关闭');
});

// 判断坐标是否在中国范围内（用于GCJ-02转换）
function outOfChina(lng, lat)
{
    return (lng < 72.004 || lng > 137.8347) || (lat < 0.8293 || lat > 55.8271);
}

// 转换算法辅助函数
function transformLat(x, y)
{
    let ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
    ret += (20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) * 2.0 / 3.0;
    ret += (20.0 * Math.sin(y * Math.PI) + 40.0 * Math.sin(y / 3.0 * Math.PI)) * 2.0 / 3.0;
    ret += (160.0 * Math.sin(y / 12.0 * Math.PI) + 320 * Math.sin(y * Math.PI / 30.0)) * 2.0 / 3.0;
    return ret;
}

function transformLng(x, y)
{
    let ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
    ret += (20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) * 2.0 / 3.0;
    ret += (20.0 * Math.sin(x * Math.PI) + 40.0 * Math.sin(x / 3.0 * Math.PI)) * 2.0 / 3.0;
    ret += (150.0 * Math.sin(x / 12.0 * Math.PI) + 300.0 * Math.sin(x / 30.0 * Math.PI)) * 2.0 / 3.0;
    return ret;
}

// WGS-84转GCJ-02坐标
function wgs84ToGcj02(wgsLng, wgsLat)
{
    if (outOfChina(wgsLng, wgsLat))
    {
        return { lng: wgsLng, lat: wgsLat };
    }

    let dLat = transformLat(wgsLng - 105.0, wgsLat - 35.0);
    let dLng = transformLng(wgsLng - 105.0, wgsLat - 35.0);
    let radLat = wgsLat / 180.0 * Math.PI;
    let magic = Math.sin(radLat);
    magic = 1 - 0.00669342162296594323 * magic * magic;
    let sqrtMagic = Math.sqrt(magic);
    dLat = (dLat * 180.0) / ((6378245.0 * (1 - 0.00669342162296594323)) / (magic * sqrtMagic) * Math.PI);
    dLng = (dLng * 180.0) / (6378245.0 / sqrtMagic * Math.cos(radLat) * Math.PI);

    let mgLat = wgsLat + dLat;
    let mgLng = wgsLng + dLng;

    return { lng: mgLng, lat: mgLat };
}

// 处理接收到的GPS数据
mqttClient.on('message', (topic, payload) => {
    try
    {
        const gpsData = JSON.parse(payload.toString());
        console.log('收到GPS数据:', gpsData);

        // 验证数据格式
        if (!gpsData.lat || !gpsData.lng)
        {
            console.warn('GPS数据缺少必要字段:', gpsData);
            return;
        }

        // 坐标转换：WGS-84 -> GCJ-02
        const convertedCoords = wgs84ToGcj02(gpsData.lng, gpsData.lat);

        // 格式化数据以匹配前端期望的格式（使用转换后的坐标）
        const formattedData = {
      longitude: convertedCoords.lng,
      latitude: convertedCoords.lat,
      altitude: gpsData.alt || 0,
      satellites: gpsData.sat || 0,
      fixQuality: gpsData.fixQuality || 1,
      time: new Date().toISOString()
      };

    // 转发给所有连接的WebSocket客户端
    wss.clients.forEach(client => {
        if (client.readyState === WebSocket.OPEN)
        {
            client.send(JSON.stringify(formattedData));
        }
    });
} catch (error) {
    console.error('解析数据失败:', error);
    console.error('原始数据:', payload.toString());
}
});

// 处理来自前端的指令
wss.on('connection', (client) => {
    console.log('新的WebSocket客户端连接');

    client.on('message', (data) => {
        try
        {
            const msg = JSON.parse(data.toString());
            if (msg.command)
            {
                console.log('收到指令:', msg.command);
                mqttClient.publish('gps/command', msg.command);
            }
        }
        catch (error)
        {
            console.error('解析指令失败:', error);
        }
    });

    client.on('close', () => {
        console.log('WebSocket客户端断开连接');
    });
});

console.log('服务器启动，监听端口 3000（HTTP）和 8080（WebSocket）');
